home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * TRACE.C
- *
- * System tracing routines
- */
-
- #include <stdio.h> /* XXX use own I/O routines */
- #include <sys/file.h> /* XXX use own I/O routines */
-
- #include "tmp/c.h"
-
- RcsId("$Header: /private/postgres/src/utils/error/RCS/trace.c,v 1.15 1991/11/11 19:31:43 mer Exp $");
-
- #include "tmp/simplelists.h"
- #include "utils/module.h"
- #include "utils/log.h"
- #include "utils/mcxt.h"
-
- #ifdef sprite
- #include "sprite_file.h"
- #include "sprite_file2.h"
- #else
- #include "storage/fd.h"
- #endif /* sprite */
-
- typedef struct {
- char *Child;
- char *Parent1;
- char *Parent2;
- } TraceHier;
-
- /*
- * This array defines the parent heirarchy. Individual modules can
- * declare local trace variables with 'parents' such that turning the
- * trace on for the parent will turn the trace on for all its children.
- *
- * CHILD PARENT#1 PARENT#2
- */
-
- static TraceHier TraceTree[] = {
- "Root", NULL, NULL,
- "Memory", "Root", NULL,
- "Parser", "Root", NULL,
- "Planner", "Root", NULL,
- "Tcop", "Root", NULL,
- "Rules", "Root", NULL,
- "Storage", "Root", NULL,
- "Executor", "Root", NULL
- };
-
-
-
- extern String getenv(); /* XXX style: use include */
-
- static GlobalMemory TraceCxt; /* used for memory allocation */
- static int TSDepth; /* how deep are we? */
- static SLList TBList; /* list of known module trace blocks */
- static SLList TSList; /* subroutine stack trace */
- static FileNumber TraceFile; /* current trace file (fdcache) */
- static char *DefaultTraceFile = "/dev/null";
-
- extern char **environ;
-
- /*
- * TraceInitialize --
- */
-
- void TraceInitialize ARGS((TraceBlock *));
- void WriteSpaces ARGS((File, int, int));
- char *TailName ARGS((char *));
- Pointer TraceAlloc ARGS((int));
- void TraceFree ARGS((Pointer, int));
-
- /*
- * Resource control
- */
-
- static int NumEnabled; /* have we been initialized? .. count # of times */
-
- void
- EnableTrace(enable)
- {
- static int fail;
-
- Assert(fail == 0);
-
- if (!enable && --NumEnabled)
- return;
- if (enable && NumEnabled++)
- return;
-
- ++fail;
- if (enable) {
- EnableFDCache(true);
- EnableMemoryContext(true);
-
- SLNewList(&TBList, offsetof(TraceBlock,Node));
- SLNewList(&TSList, offsetof(TraceStack,Node));
- TraceCxt = CreateGlobalMemory("Trace");
- InitializeTheGlobalArray();
- if (getenv("TRACEFILE"))
- DefaultTraceFile = getenv("TRACEFILE");
- TraceFile =
- FileNameOpenFile(DefaultTraceFile,O_WRONLY|O_APPEND|O_CREAT,0666);
- Assert(TraceFile >= 0);
- {
- register char *ptr;
- register short i, j;
- char tracename[128];
-
- for (i = 0; ptr = environ[i]; ++i) {
- uint32 traceLevel;
- if (strncmp(ptr, "TRACE_", 6) != 0)
- continue;
- strcpy(tracename, ptr + 6);
- for (j = 0; tracename[j] && tracename[j] != '='; ++j);
- tracename[j] = 0;
- traceLevel = atoi(tracename + j + 1);
- if (traceLevel == 0)
- traceLevel = 1;
- SetTraceLevel(tracename, traceLevel);
- }
- }
- } else {
- {
- register TraceBlock *tb;
-
- while (tb = (TraceBlock *)SLRemHead(&TBList)) {
- tb->Flags = 0;
- tb->Level = 0;
- }
- }
- DefaultTraceFile = "/dev/tty";
- GlobalMemoryDestroy(TraceCxt);
- EnableFDCache(false);
- EnableMemoryContext(false);
- }
- --fail;
- }
-
- _TraceMsg(tb, level, nargs, arg0)
- TraceBlock *tb;
- int level, nargs;
- Pointer arg0;
- {
- Assert(NumEnabled);
- if ((tb->Flags & TBF_INITIALIZED) == 0)
- TraceInitialize(tb);
- if (level <= tb->Level) {
- Pointer *args = &arg0;
- char buf[1024];
- int len;
-
- sprintf(buf, args[0], args[1], args[2], args[3], args[4], args[5]);
- len = strlen(buf);
- Assert(len < sizeof(buf));
- buf[len++] = '\n';
- switch(tb->Stream) {
- case DefaultStream:
- case LogStream:
- case InstallationStream:
- case DBStream:
- case ConsoleStream:
- case FrontendStream:
- case PostmasterStream:
- case AuxStream:
- FileWrite(TraceFile, buf, len);
- break;
- default:
- elog(WARN, "Unknown trace stream %s %d", tb->Name, tb->Stream);
- break;
- }
- }
- }
-
- /*
- * If not already initialized, initialize a trace block.
- */
-
- void
- TraceInitialize(tb)
- TraceBlock *tb;
- {
- if (tb->Flags & TBF_INITIALIZED)
- return;
-
- Assert(NumEnabled);
-
- /*
- * Remove header and tailer spaces from Parent1 and Parent2 that might
- * have been stuck in by cpp.
- */
-
- RemoveHeadTailSpaces(&tb->Parent1);
- RemoveHeadTailSpaces(&tb->Parent2);
-
- /*
- * Initial trace level determined by max of any parent's trace level.
- */
-
- {
- uint32 l1 = TraceLevelByName(tb->Parent1);
- uint32 l2 = TraceLevelByName(tb->Parent2);
-
- tb->Level = Max(l1,l2);
- }
-
- /*
- * Trace level overriden by specific level already set for this name
- * (level for all matched names are the same)
- */
-
- {
- register TraceBlock *t, *tnext;
- for (t = (TraceBlock *)SLGetHead(&TBList); t; t = tnext) {
- tnext = (TraceBlock *)SLGetSucc(&t->Node);
- if (strcmp(tb->Name, t->Name) == 0) {
- tb->Level = t->Level;
- break;
- }
- }
- }
-
- /*
- * Add trace block to TB list.
- */
-
- SLNewNode(&tb->Node);
- SLAddTail(&TBList, &tb->Node);
- tb->Flags |= TBF_INITIALIZED;
- }
-
- RemoveHeadTailSpaces(str)
- char **str;
- {
- register char *ptr = *str;
-
- if (ptr) {
- while (*ptr == ' ' || *ptr == '\t')
- ++ptr;
- *str = ptr;
- while (*ptr && *ptr != ' ' && *ptr != '\t')
- ++ptr;
- *ptr = 0;
- }
- }
-
- InitializeTheGlobalArray()
- {
- register short i;
-
- for (i = 0; i < lengthof(TraceTree); ++i) {
- register TraceBlock *tb = (TraceBlock *)TraceAlloc(sizeof(TraceBlock));
- bzero(tb, sizeof(TraceBlock));
- tb->Name = TraceTree[i].Child;
- tb->Parent1 = TraceTree[i].Parent1;
- tb->Parent2 = TraceTree[i].Parent2;
- tb->Flags = TBF_INITIALIZED;
- SLNewNode(&tb->Node);
- SLAddTail(&TBList, &tb->Node);
- }
- }
-
- /*
- * TraceLevelByName()
- *
- * Return the trace level associated with the given trace variable
- * name. (0 if not found)
- */
-
- static
- int
- TraceLevelByName(name)
- char *name;
- {
- register TraceBlock *tb;
-
- Assert(NumEnabled);
- if (name == NULL)
- return(0);
- for (tb = (TraceBlock *)SLGetHead(&TBList); tb;
- tb = (TraceBlock *)SLGetSucc(&tb->Node))
- {
- if (strcmp(tb->Name, name) == 0)
- return(tb->Level);
- }
- return(0);
- }
-
- /*
- * SetChildrenOf()
- *
- * Subroutine used by SetTraceLevel() to search out the children of
- * a name and modify their level recursively.
- */
-
- static void
- SetChildrenOf(Name, level)
- char *Name;
- {
- register TraceBlock *tb;
-
- Assert(NumEnabled);
-
- for (tb = (TraceBlock *)SLGetHead(&TBList); tb;
- tb = (TraceBlock *)SLGetSucc(&tb->Node))
- {
- if (tb->Parent1 && strcmp(tb->Parent1, Name) == 0) {
- if (tb->Flags & TBF_FAULT) /* circular tree! */
- Assert(0);
- tb->Level = level;
- tb->Flags |= TBF_FAULT;
- SetChildrenOf(tb->Name, level);
- tb->Flags &= ~TBF_FAULT;
- }
- if (tb->Parent2 && strcmp(tb->Parent2, Name) == 0) {
- if (tb->Flags & TBF_FAULT) /* circular tree! */
- Assert(0);
- tb->Level = level;
- tb->Flags |= TBF_FAULT;
- SetChildrenOf(tb->Name, level);
- tb->Flags &= ~TBF_FAULT;
- }
- }
- }
-
- /*
- * SetTraceLevel()
- *
- * Modify the current trace level for the given trace variable. 0 turns
- * off the trace. The level for all children is recursively set to
- * this value too.
- *
- * Note that more than one traceblock with the same name may exist.
- */
-
- void
- SetTraceLevel(traceName, level)
- char *traceName;
- int level;
- {
- short found = 0;
-
-
- Assert(NumEnabled);
-
- /*
- * Step (1), search list and update any matches.
- */
-
- {
- register TraceBlock *tb;
-
- for (tb = (TraceBlock *)SLGetHead(&TBList); tb;
- tb = (TraceBlock *)SLGetSucc(&tb->Node))
- {
- if (strcmp(traceName, tb->Name) == 0) {
- tb->Level = level;
- found = 1;
- }
- }
- }
-
- /*
- * Step (2), update children of this trace name, if any (recur)
- */
-
- SetChildrenOf(traceName, level);
-
- /*
- * Step (3), if name was not in block list, add to block list.
- */
-
- if (found == 0) {
- register TraceBlock *tb = (TraceBlock *)TraceAlloc(sizeof(*tb));
- char *ptr = TraceAlloc(strlen(traceName)+1);
-
- SLNewNode(&tb->Node);
- strcpy(ptr, traceName);
- tb->Name = ptr;
- tb->Flags = TBF_INITIALIZED;
- tb->Level = level;
- SLAddHead(&TBList, &tb->Node);
- }
- }
-
- /*
- * Change the TraceFile messages are sent to. On failure, the old trace
- * file continues to be used.
- */
-
- bool
- TraceFileName(fileName)
- char *fileName;
- {
- FileNumber newfile;
- char buf[256];
-
- newfile = FileNameOpenFile(fileName,O_WRONLY|O_APPEND|O_CREAT,0666);
- if (newfile < 0) {
- sprintf(buf, "Unable to open new trace file %s\n", fileName);
- FileWrite(TraceFile, buf, strlen(buf));
- return(false);
- }
- FileClose(TraceFile);
- TraceFile = newfile;
- return(true);
- }
-
- /*
- * Subroutine Call/Return tracing
- */
-
- void
- _TracePush(tb, lineno, str)
- TraceBlock *tb;
- int lineno;
- char *str;
- {
- register TraceStack *ts;
-
- Assert(NumEnabled);
- if ((tb->Flags & TBF_INITIALIZED) == 0)
- TraceInitialize(tb);
-
- ts = (TraceStack *)TraceAlloc(sizeof(*ts));
- ts->Tb = tb;
- ts->LineNo = lineno;
- ts->Text = str;
- SLNewNode(&ts->Node);
- SLAddTail(&TSList, &ts->Node);
- ++TSDepth;
-
- if (tb->Level) {
- char buf[256];
- WriteSpaces(TraceFile, TSDepth, '#');
- sprintf(buf, "BEGIN %s.%d %s\n", TailName(tb->Module), lineno, str);
- FileWrite(TraceFile, buf, strlen(buf));
- }
- }
-
- void
- _TracePop(tb, lineno, str)
- TraceBlock *tb;
- int lineno;
- char *str;
- {
- register TraceStack *ts = (TraceStack *)SLGetTail(&TSList);
-
- Assert(PointerIsValid(ts));
- Assert(ts->Tb == tb);
- SLRemove(&ts->Node);
- TraceFree((Pointer)ts, sizeof(*ts));
-
- if (str[0] == '\0')
- str = ts->Text;
-
- if (tb->Level) {
- char buf[256];
- WriteSpaces(TraceFile, TSDepth, '#');
- sprintf(buf, "END %s.%d %s\n", TailName(tb->Module), lineno, str);
- FileWrite(TraceFile, buf, strlen(buf));
- }
- --TSDepth;
- }
-
- void
- _TraceReset(tb, lineno, str)
- TraceBlock *tb;
- int lineno;
- char *str;
- {
-
- }
-
- /*
- * Called by exception handler
- */
-
- void
- _TraceDump()
- {
- TraceStack *ts;
- char buf[256];
- static int ReEntered = 0;
-
- if (NumEnabled <= 0)
- return;
- if (ReEntered)
- exitpg(1234);
- ++ReEntered;
-
- sprintf(buf, "\nTRACE STACK DUMP\n");
- FileWrite(TraceFile, buf, strlen(buf));
-
- for (ts = (TraceStack *)SLGetHead(&TSList);
- PointerIsValid(ts);
- ts = (TraceStack *)SLGetSucc(&ts->Node))
- {
- sprintf(buf, "%15s.%-4d\t%s\n", ts->Tb->Module, ts->LineNo, ts->Text);
- FileWrite(TraceFile, buf, strlen(buf));
- }
- sprintf(buf, "\nTRACE STACK END\n");
- FileWrite(TraceFile, buf, strlen(buf));
- --ReEntered;
- }
-
- static void
- WriteSpaces(file, n, firstchar)
- FileNumber file;
- int n;
- int firstchar;
- {
- char buf[256];
- int i;
-
- ++n;
- for (i = 0; i < n && i < sizeof(buf); ++i)
- buf[i] = ' ';
- buf[0] = '#';
- while (n > sizeof(buf)) {
- FileWrite(file, buf, n);
- buf[0] = ' ';
- n -= sizeof(buf);
- }
- FileWrite(file, buf, n);
- }
-
- char *
- TailName(str)
- char *str;
- {
- char *ptr = str + strlen(str);
- while (ptr >= str && *ptr != '/')
- --ptr;
- return(ptr + 1);
- }
-
- /*
- * ALLOCATION AND FREEING OF MEMORY
- *
- * Allocations smaller than 32 longwords are tabled for fast access.
- * (that is, TraceFree() calls table the pointer instead of freeing it)
- */
-
- static char **AllocArray[32];
-
- Pointer
- TraceAlloc(bytes)
- {
- int longwords;
- char **res;
-
- if (bytes < sizeof(char *))
- bytes = sizeof(char *);
- longwords = (bytes + 3) >> 2; /* # of longwords to allocate */
- if (longwords >= lengthof(AllocArray) || AllocArray[longwords] == NULL) {
- return(MemoryContextAlloc((MemoryContext)TraceCxt, longwords << 2));
- }
- res = AllocArray[longwords];
- AllocArray[longwords] = (char **)res[0];
- return((Pointer)res);
- }
-
- void
- TraceFree(ptr, bytes)
- Pointer ptr;
- int bytes;
- {
- int longwords;
- if (bytes < sizeof(char *))
- bytes = sizeof(char *);
- longwords = (bytes + 3) >> 2; /* # of longwords to free */
-
- if (longwords >= lengthof(AllocArray)) {
- MemoryContextFree((MemoryContext)TraceCxt, ptr);
- return;
- }
- *(char **)ptr = (char *)AllocArray[longwords];
- AllocArray[longwords] = (char **)ptr;
- }
-
-
-